<?php

require_once 'Custom/Model/Db.php';

class Category extends Custom_Model_Db
{
	/**
	 * The default table name 
	 */
    protected $_name 			= 	'category';
    protected $_primary 		=	'id';
	
    
	/**
     * 取到期中一条数据
     * @param int $id
     */
	public function getNode($id){
		try {
			$id=(int)$id;
			$where = "id=$id";
            $result = $this->fetchRow($where);
            if($result){
            	$result=$result->toArray();
            	return $result;
            }else{
            	return false;
            }
        } catch (Exception $e) {
			return false;
        }
	}
	
	
    /**
     * 取到此ID下的所有子类数据
     * @param int $id
     * @param boolean  $recursive
     */
	public function getChildrenID($id,$recursive = false){
		try {
			$children=array();
			$id=(int)$id;
			$db = $this->getAdapter();
			if($recursive){
				$node=$this->getNode($id);
				$where=" lnode>= ".$node['lnode']." AND rnode<=".$node['rnode']."";
				$order="lnode ASC";
				$sql=$db->select()
				->from(array($this->_name),'*')
				->where($where)
				->order($order);
			}else{
				$where="parentid='$id'";
				$order="position ASC";
				$sql=$db->select()
				->from(array($this->_name),'*')
				->where($where)
				->order($order);
			}
			$data=$db->fetchAll($sql);
			if(is_array($data))foreach($data as $val){
				$children[]=$val['id'];
				
			}
			$catearr=implode(',', $children);
        	return $catearr;
        } catch (Exception $e) {
			return false;
        }
	
	}
    
    /**
     * 取到此ID下的所有子类数据
     * @param int $id
     * @param boolean  $recursive
     */
	public function getChildren($id,$recursive = false){
		try {
			$children=array();
			$id=(int)$id;
			$db = $this->getAdapter();
			if($recursive){
				$node=$this->getNode($id);
				$where=" lnode>= ".$node['lnode']." AND rnode<=".$node['rnode']."";
				$order="lnode ASC";
				$sql=$db->select()
				->from(array($this->_name),'*')
				->where($where)
				->order($order);
			}else{
				$where="parentid='$id'";
				$order="position ASC";
				$sql=$db->select()
				->from(array($this->_name),'*')
				->where($where)
				->order($order);
			}
			$data=$db->fetchAll($sql);
			if(is_array($data))foreach($data as $val){
				$children[$val['id']]=$val;
				$children[$val['id']]['nums']=($val['rnode']-$val['lnode']-1)/2;
			}
        	return $children;
        } catch (Exception $e) {
			return false;
        }
	
	}
	
	/**
	 * 取到此分类的树型分类路径
	 * @param int $id
	 */
	public function getPath($id){
		try {
			$path = array();
			$id=(int)$id;
			$db = $this->getAdapter();
			$node=$this->getNode($id);
			
			$where=" lnode<=".$node['lnode']." AND rnode>=".$node['rnode']."";
			$order="lnode ASC";
			$sql=$db->select()
			->from(array($this->_name),'*')
			->where($where)
			->order($order);
			
			$data=$db->fetchAll($sql);
			if(is_array($data))foreach($data as $val){
				$path[$val['id']]=$val;
			}
        	return $path;
        } catch (Exception $e) {
			return false;
        }
	
	}
	
	/**
	 * 取到此分类的树型分类路径
	 * @param int $id
	 */
	public function getPathName($id){
		try {
			$path = array();
			$id=(int)$id;
			$db = $this->getAdapter();
			$node=$this->getNode($id);
			
			$where=" lnode<=".$node['lnode']." AND rnode>=".$node['rnode']." AND parentid>1";
			$order="lnode ASC";
			$sql=$db->select()
			->from(array($this->_name),'*')
			->where($where)
			->order($order);
			
			$data=$db->fetchAll($sql);
			if(is_array($data))foreach($data as $val){
				$path[$val['id']]=$val;
			}
        	return $path;
        } catch (Exception $e) {
			return false;
        }
	
	}
	
	/**
	 * 对其中一条数据进行修改
	 * @param $id
	 */
	public function	remove($id){
		//根分类不能删除
		$id=(int)$id;
		if($id === 1) { return false; }
		try {
        	$node=$this->getNode($id);
        	$lnode = (int)$node['lnode'];
			$rnode = (int)$node['rnode'];
			$parentid = (int)$node['parentid'];
			$position = (int)$node['position'];
			$number = $rnode - $lnode + 1;
			$db = $this->getAdapter();
			//先删除id节点和它下面所有的节点数据
			$where=" lnode>=$lnode AND rnode<=$rnode ";
			
			$result=$this->delete($where);
			if($result){
				//接着更新其他存在数据库内的左节点数值
				$data = array('lnode' => new Zend_DB_Expr("lnode-$number"));
				$db->update($this->_name,$data,"lnode>$rnode");
				
				//再更新其他存在数据库内的右结点数值
				$data = array('rnode' => new Zend_DB_Expr("rnode-$number"));
				$db->update($this->_name,$data,"rnode>$lnode");
				
				//最后更新数据库内数据的位置
				$data = array('position' => new Zend_DB_Expr("position-1"));
				$db->update($this->_name,$data,"parentid=$parentid AND position>$position");
				return true;
			}else{
				return false;
			}
        } catch (Exception $e) {
			return false;
        }
	}
	
	public	function move($id, $rid, $position = 0, $iscopy = false){
		
		try {
			$id=(int)$id;
			$rid=(int)$rid;
			if((int)$rid === 0 ||$id === 1) { return false; }
			$db = $this->getAdapter();
							
			$node		= $this->getNode($id);		
			$nchildren	= $this->getChildren($id);	
			$ref_node	= $this->getNode($rid);	
			$rchildren	= $this->getChildren($rid);
			$ndif = 2;
			$node_ids = array(-1);
			if($node !== false) {
				$node_ids = array_keys($this->getChildren($id, true));
				if(in_array($rid, $node_ids)) return false;
				$ndif = $node['rnode'] - $node['lnode'] + 1;
				
			}
			
			if($position >= count($rchildren)) {
				$position = count($rchildren);
			}
			
			$nodeidstring=implode(",", $node_ids);
			
			if($node !== false && $iscopy == false) {
				
				$data = array('position' => new Zend_DB_Expr("position-1"));
				$where="parentid = ".$node['parentid']." AND position >".$node['position']."";
				$db->update($this->_name,$data,$where);
				
				$data = array('lnode' => new Zend_DB_Expr("lnode-$ndif"));
				$where="lnode > ".$node['rnode']." ";
				$db->update($this->_name,$data,$where);
				
				$data = array('rnode' => new Zend_DB_Expr("rnode-$ndif"));
				$where="rnode > ".$node['lnode']." AND id NOT IN ( $nodeidstring ) ";
				
				$db->update($this->_name,$data,$where);
				
				
			}
			$iscopywhere=($iscopy)?"":" AND id NOT IN ( $nodeidstring ) ";
			
			$data = array('position' => new Zend_DB_Expr("position+1"));
			$where="parentid= $rid AND position >= $position ".$iscopywhere;
			$db->update($this->_name,$data,$where);		
			
			$ref_ind = $rid === 0 ? (int)$rchildren[count($rchildren) - 1]['rnode'] + 1 : (int)$ref_node['rnode'];
			$ref_ind = max($ref_ind, 1);
	
			$self = ($node !== false && !$iscopy && (int)$node['parentid'] == $rid && $position > $node['position']) ? 1 : 0;
			foreach($rchildren as $k => $v) {
				if($v['position'] - $self == $position) {
					$ref_ind = (int)$v['lnode'];
					break;
				}
			}
			if($node !== false && !$iscopy && $node['lnode'] < $ref_ind) {
				$ref_ind -= $ndif;
			}
			
			
			$data = array('lnode' => new Zend_DB_Expr("lnode+$ndif"));
			$where="lnode >= $ref_ind ".$iscopywhere;
			$db->update($this->_name,$data,$where);	
			
			$data = array('rnode' => new Zend_DB_Expr("rnode+$ndif"));
			$where="rnode >= $ref_ind ".$iscopywhere;
			$db->update($this->_name,$data,$where);	
	
	
			$levelval = $rid == 0 ? 0 : $ref_node['level'] + 1;
			$idif = $ref_ind;
			if($node !== false) {
				$levelval = $node['level'] - ($ref_node['level'] + 1);
				$idif = $node['lnode'] - $ref_ind;
				if($iscopy) {
					$sql="INSERT INTO ".$this->_name." (parentid,position,lnode,rnode,level)". 
						"SELECT " . 
							"".$rid.", " . 
							"position, " . 
							"lnode - (".($idif + ($node["lnode"] >= $ref_ind ? $ndif : 0))."), " . 
							"rnode - (".($idif + ($node["lnode"] >= $ref_ind ? $ndif : 0))."), " . 
							"level - (".$levelval.") " . 
						"FROM `".$this->_name."` " . 
						"WHERE " . 
							" id IN (".$nodeidstring.") " . 
						"ORDER BY level  ASC";
					
					/*
			    	$select = $db->select();
					$select->from($this->_name, array('parentid','position','name','lnode','rnode','level','type'))
							->where("id IN  ( $nodeidstring )")
						   	->order('level ASC ');
					$selectquery = $select->__toString();//生成SQL语句
					$sql=$insertquery.'('.$selectquery.')';
					*/ 
					
					$obj = $db->query($sql);
					$insertid =$db->lastInsertId();
		        	
				}else {
					
					$data = array('position' => $position,'parentid' => $rid);
					$where="id = $id";
					$db->update($this->_name,$data,$where);
					
					$data = array(	'lnode' => new Zend_DB_Expr("lnode-($idif)"),
								  	'rnode' => new Zend_DB_Expr("rnode-($idif)"),
									'level' => new Zend_DB_Expr("level-($levelval)"),
									);
					
					$where="id IN  ($nodeidstring)";
					$db->update($this->_name,$data,$where);	
				}
			}else {
				$data=array('parentid'=>$rid,
							'position'=>$position,
							'lnode'=>$idif,
							'rnode'=>$idif + 1,
							'level'=>$levelval);	
				
				$result = $this->createRow($data);
	        	$insertid=$result->save();
			}
	
			if($iscopy) $this->docopy($insertid, $position);
			return $node === false || $iscopy ? $insertid : true;
		} catch (Exception $e) {
			return false;
        }
	}
	
	/**
	 * 复制分类
	 * @param $id
	 * @param $position
	 */
	public	function docopy($id,$position){
		try{
			$id=(int)$id;
			$node = $this->getNode($id);
			
			$children = $this->getChildren($id, true);
			
			$db = $this->getAdapter();
			$map = array();
			for($i = $node['lnode'] + 1; $i < $node['rnode']; $i++) {
				$map[$i] = $id;
			}
			
			foreach($children as $cid => $child) {
				if((int)$cid ==$id) {
					$db->update($this->_name,array('position'=>$position),"id=$cid");
					continue;
				}
				$db->update($this->_name,array('parentid'=>$map[$child["lnode"]]),"id=$cid");
				for($i = $child['lnode'] + 1; $i < $child['rnode']; $i++) {
					$map[$i] = $cid;
				}
			}
		} catch (Exception $e) {
			return false;
        }
	}
    
    public function setdata($data){
    	try{
	    	$db = $this->getAdapter();
	    	$key=array_keys($db->describeTable($this->_name));
	    	$addfields=array("name" => "name", "type" => "type");
	    	$fields=array_combine($key, $key);
	    	$fields = array_merge($fields, $addfields);
	    	
	    	
	    	$sql = "UPDATE ".$this->_name." SET ".$fields["id"]." = ".$fields["id"]." "; 
			if(is_array($data))foreach($addfields as $k => $v) {
				if(isset($data[$k]))	$sql .= ", ".$fields[$v]." = \"".$data[$k]."\" ";
				else					$sql .= ", ".$fields[$v]." = ".$fields[$v]." ";
			}
			$sql .= "WHERE ".$fields["id"]." = ".(int)$data["id"];
			
			$obj = $db->query($sql);
			
    	} catch (Exception $e) {
			return false;
        }
		
    }
    
    /**
     * 复制分类
     * @param $data
     * @param $ids
     */
    public function copydata($data,$ids){
    	try{
	    	$db = $this->getAdapter();
	    	$key=array_keys($db->describeTable($this->_name));
	    	$addfields=array("name" => "name", "type" => "type");
	    	$fields=array_combine($key, $key);
	    	$fields = array_merge($fields, $addfields);
	    	
    		$i = 0;
			if(is_array($data))foreach($data as $dk => $dv) {
				$sql = "UPDATE ".$this->_name." SET ".$fields["id"]." = ".$fields["id"]." ";  
				foreach($addfields as $k => $v) {
					if(isset($dv[$k]))	$s .= ", ".$fields[$v]." = \"".$dv[$k]."\" ";
					else				$s .= ", ".$fields[$v]." = `".$fields[$v]."` ";
				}
				$s .= "WHERE ".$fields["id"]." = ".$ids[$i];
				$obj = $db->query($sql);
				$i++;
			}

    	} catch (Exception $e) {
			return false;
        }
        
		
    }
    
    
    
    /**
     * 增加
     * @param array $data
     */
	public function add($parent, $position){
		try {
			return $this->move(0,$parent, $position);
        } catch (Exception $e) {
			return false;
        }
	}
	
	
	
	
	/**
	 * 修改
	 * @param array $data
	 * @param int $id
	 */
	public function edit(array $data,$id){
		try {
			$where = $this->select()->where("id=?",$id);
			$result = $this->fetchRow($where);
			$result->setFromArray($data);	       
			$id=$result->save();
        	return $id;
        } catch (Exception $e) {
			return false;
        }
	}
	
	/**
	 * 查找分类
	 * @param string $keywords
	 */
	public function search($keywords){
		
		try {
			$result=array();
			$db = $this->getAdapter();
			$where=" name LIKE  '%".$keywords."%' ";
			$sql=$db->select()
			->from(array($this->_name),array('lnode','rnode'))
			->where($where);
			$data=$db->fetchAll($sql);
			if(count($data)==0) return $result;
			$sqls="SELECT DISTINCT id FROM ".$this->_name." WHERE 0 ";
			if(is_array($data))foreach($data as $key=>$val){
				$sqls.= " OR ( lnode < ".$val['lnode']." AND rnode > ".$val['rnode'].") ";
			}
			$data=$db->fetchAll($sqls);
			if(is_array($data))foreach($data as $key=>$val){
				$result[]=$val['id'];
			}
        	return $result;
        } catch (Exception $e) {
			return false;
        }
	
	}
    
	
}
